<?php

/**
 * 核心操作类，实现采集以及展现部分
 * @author elsesky
 *
 */
class flyluomanager implements IflyluoManager {
	private $st;
	private $tid;
	private $listnum;
	private $kw;
	private $ccount; 
	
	
//-----------------------主页面功能部分----------------------------------------	
	/**
	 * 用于单个漫画采集
	 * @param int $tid	用于设置需要采集的漫画的ID
	 */
	public function get_sig($tid,$with_notifacation=false,$with_crawnotify=false){
		$this->tid = $tid;
		$url = $this->make_manga_url($tid);
		//获取URL内容(由于原站是GB，需转码）
		$content = 	$this->gb2u8(file_get_contents($url));
		
		//测试用代码
		//$content = $this->gb2u8(file_get_contents('list.txt'));
		
		//页面分析开始
		//获取名称
		try {
			$name = $this->get_manga_name($content);
		} catch (Exception $e) {
			if ($with_notifacation) {
				show_normal_mesR($e->getMessage(),'名称获取失败','名称获取');
			}
		}
		//获取最后更新时间
		try {
			$dt = $this->get_manga_lastupdate($content);
		} catch (Exception $e) {
			if ($with_notifacation) {
				show_normal_mesR($e->getMessage(),'更新日期获取失败','更新日期获取');
			}
		}
		//获取URL列表(注意空内容异常)
		try {
			$urls = $this->get_page_urllist($content);
		} catch (Exception $e) {
			if ($with_notifacation) {
				show_normal_mesR($e->getMessage(),'URL列表获取失败','URL列表获取');
			}
		}
		//通过URL列表获取单位总数
		$ulnum = count($urls);
		//插入分类信息
		$this->create_name($this->tid, $dt, $name);
		//获取数据库中总数
		$dbcount = $this->get_id_count_db($this->tid);
		//由于是逆序，需要倒装数组
		$urln = array_reverse($urls);
		//注销页面内容变量
		unset($content);
		
		
		//开始进入页面采集循环
		foreach ($urls as $k=>$v) {
			//当COUNT小于已经采集的时候，跳过。
			if ($k < $dbcount) {
				continue;
			}
			$current_url = FLYLUO_URL_HTTP_HEADER . $v;
			$comic_contents = $this->gb2u8(file_get_contents($current_url));
			
			
			//测试用代码
			//$comic_contents = $this->gb2u8(file_get_contents('piclist.txt'));
			
			
			//获取页面图片
			try {
				$c_urls = $this->get_pic_urls($comic_contents);
			} catch (Exception $e) {
				if ($with_notifacation) {
					//由于报错中断，需删除已经插入部分
					$this->clear_err_picins($this->tid);
					$this->clear_err_tagnums($this->tid);
					show_normal_mesR($e->getMessage(),'图片列表获取失败','图片列表获取');
				}
			}
			//入库
			$this->do_picinsert($tid, $c_urls);
			//更新漫画信息
			$this->update_manga_info($tid, $dt, $ulnum);
		}
		if ($with_crawnotify) {
			echo '漫画" ' . $name . ' "采集完毕<BR>';
			ob_flush();
		}
		
	}
	
	/**
	 * 用于连载漫画采集
	 * @param bool $with_notifacation	设置出错时是否中断报错
	 */
	public function get_all_lianzai($with_notifacation=false){
		$content = $this->gb2u8(file_get_contents($this->make_lianzai_page_url(0)));
		try {
			//获取总页数
			$totalpages = $this->get_lianzai_total_pgs($content);
			unset($content);
			//开始页面循环
			for ($i = 1; $i <= $totalpages; $i++) {
				$cc = $this->gb2u8(file_get_contents($this->make_lianzai_page_url($i)));
				$ids = $this->get_lianzai_manga_ids_by_pg($cc);
				foreach ($ids as $value) {
					$this->get_sig($value,$with_notifacation,true);
				}
			}
		} catch (Exception $e) {
			if ($with_notifacation) {
				show_normal_mesR($e->getMessage(),'采集失败','总采集');;
			}
		}
		
	}
	
	/**
	 * 显示默认页
	 * @param string array() $sysinfo	系统信息数组
	 * @param int $st					当前页面列表
	 * @param int $listnum				每页列表数
	 * @param int $ccount				常用漫画列表显示数
	 */
	public function	get_index_pg($sysinfo,$st=0,$listnum=20,$ccount = 9){
		$this->get_search_pg($sysinfo,'',$st,$listnum,$ccount);
	}
	
	/**
	 * 显示搜索结果列表页
	 * @param string array() $sysinfo	系统信息数组
	 * @param string $kw				查询关键字
	 * @param int $st					当前页面列表
	 * @param int $listnum				每页列表数
	 * @param int $ccount				常用漫画列表显示数
	 */
	public function get_search_pg($sysinfo,$kw='',$st=0,$listnum=20,$ccount = 9){
		$this->listnum = $listnum;
		$this->st = $st;
		$this->kw = $kw;
		$this->ccount = $ccount;
		
		
		global $DB;
		$array_piclist = array();
		//如果没有关键字则直接作为INDEX列表
		if ($this->kw == '') {
			$DB->build_query(array(
				'select' 	=> 'id,name,lastupdate,count',
				'from'		=> 'flyluotags',
				'order'		=> 'lastupdate DESC',
				'limit'		=> array($st,$listnum)
			));
		}else {
			$DB->build_query(array(
				'select' 	=> 'id,name,lastupdate,count',
				'from'		=> 'flyluotags',
				'order'		=> 'lastupdate DESC',
				'where'		=> 'name like "%' . $this->kw . '%"' ,
				'limit'		=> array($st,$listnum)
			));
		}
		$qid = $DB->exec_query();
		$i = 0;
		//构造显示数组
		while ($row = $DB->fetch_row($qid)) {
			if($row['lastupdate'] <= 0) $row['lastupdate'] = 0;
			$array_piclist[$i]['tagname'] = $row['name'];
			$array_piclist[$i]['id'] = $row['id'];
			$array_piclist[$i]['count'] = $row['count'];
			$array_piclist[$i]['lastupdate'] = get_date_time($row['lastupdate']);
			$array_piclist[$i]['downloadpicslink'] = $this->make_downloadpicslink($row['id']); 
			$array_piclist[$i]['picslink'] = $this->make_picslink($row['id']);
			$array_piclist[$i]['getnewlink'] = $this->make_getnewlink($row['id']);
			$i++;
		}
		
		//构造分页
		$pagelink = $this->make_pagelinks();
		//构造最常访问
		$array_ccount = $this->get_most_often_seem();
		
		
		//模板处理对象
		$page = $this->smarty_show($array_piclist, $sysinfo, $pagelink, $array_ccount);
		//显示
		$page->output();
		
	}
	/**
	 * 显示最终图片下载列表
	 * @param int $tid	漫画ID
	 * @param string $type	采集类型
	 */
	public function get_pics_result($tid,$type){
		$pics = $this->make_manga_pic_links($tid);
		
		if($type == 'getpicurls'){
			echo '<textarea rows="20" cols="80" tabindex="2" class="txtarea">' . $pics . '</textarea>';
		}
		else if($type == 'getpicfiles'){
			
			header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
			header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
			header("Content-Type: text/plain; charset=UTF-8");
			header("Content-Disposition: attachment;filename=\"$tid.lst\"");
			echo $pics;
		}
		//更新访问计数
		$this->update_count($tid);
		
	} 
	
	
	
//-----------------------页面分析函数部分-------------------------------------
	/**
	 * 从页面内容中获取漫画名称
	 * @param string $content	页面内容
	 */
	private function get_manga_name($content){
		try {
			$name = explode('<TITLE>',$content);
			$name = $name[1];
			$name = explode(' -',$name);
			$name = ADD_addslashes($name[0],true);
			if ($name == '') {
				$name = explode('<title>',$content);
				$name = $name[1];
				$name = explode(' -',$name);
				$name = ADD_addslashes($name[0],true);;
			}
			if ($name == '') {
				throw new Exception('漫画名称分析失败，请确认源页面是否已经发生改变');
			}
		} catch (Exception $e) {
			throw $e;
		}
		return $name;
	} 
	/**
	 * 从页面内容中获取最后更新时间
	 * @param string $content	页面内容
	 */
	private function get_manga_lastupdate($content){
		try {
			$dt = explode('更新时间：</EM>',$content);
			$dt = $dt[1];
			$dt = explode(' </LI>',$dt);
			$dt = strtotime(trim($dt[0]));
			if ($dt == '') {
				$dt = explode('更新时间：</em>',$content);
				$dt = $dt[1];
				$dt = explode('</li>',$dt);
				$dt = strtotime(trim($dt[0]));;
			}
			if ($dt == '') {
				throw new Exception('漫画更新日期分析失败，请确认源页面是否已经发生改变');
			}
		} catch (Exception $e) {
			throw $e;
		}
		return $dt;
	}
	/**
	 * 从页面内容中获取页面列表
	 * @param string $content	页面内容
	 * @throws Exception
	 */
	private function get_page_urllist($content) {
		//分离话数列表
		try {
			$ct = explode('<UL class=global_tx_list4_1>',$content);
			$ct = $ct[1];
			$ct = explode('</UL></DIV>',$ct);
			$ct = $ct[0];
			if ($ct == '') {
				$ct = explode('<ul class="global_tx_list4_1">',$content);
				$ct = $ct[1];
				$ct = explode('</ul>',$ct);
				$ct = $ct[0];
			}
			//是否能够成功抽取
			if ($ct == '') {
				throw new Exception('列表内容分析失败，请确认源页面是否已经发生改变');
			}
		} catch (Exception $e) {
			throw $e;
		}
		
		//抽取每话连接
		$match_str = "/href=\"(.*)\"/isU";
		preg_match_all($match_str,$ct,$urln);
		return $urln[1];
	}
	/**
	 * 获取图片URL列表
	 * @param unknown_type $comic_contents
	 * @throws Exception
	 */
	private function get_pic_urls($comic_contents) {
		try {
			$pct = explode('<DIV class=piclist_001><UL>',$comic_contents);
			$pct = $pct[1];
			$pct = explode('</UL></DIV>',$pct);
			$pct = $pct[0];
			if ($pct == '') {
				$pct = explode('<div class="piclist_001"><ul>',$comic_contents);
				$pct = $pct[1];
				$pct = explode('</ul></div>',$pct);
				$pct = $pct[0];
			}
			
			
			//用于测试由于采集内容为空中断时清空漫画内容的代码
			//$pct = '';
			
			
			
			//是否能够成功抽取
			if ($pct == '') {
				throw new Exception("漫画页面列表内容分析失败，请确认源页面是否已经发生改变<br>且由于中断，该漫画内容已经被全部删除，请重新采集");
			}
		} catch (Exception $e) {
			throw $e;
		};
		//通过正则获取具体链接
		$match_str = "/original=\"(.*)\"/isU";
		preg_match_all($match_str,$pct,$purln);
		$purln = $purln[1];
		foreach ($purln as $k => $v) {
			$purln[$k] = $this->thumb2org($v);
		}
		return $purln;
	}
	/**
	 * 将连接中的缩略图还原为原图
	 * @param unknown_type $urls
	 */
	private function thumb2org($urls) {
			return str_ireplace('.thumb','',$urls);
	}
	
	
	
	
	
//----------------------全局循环的页面分析函数部分-----------------------------	
	/**
	 * 提取连载页的总页面数用于大循环
	 * @param string $content	页面内容
	 * @throws Exception
	 */
	private function get_lianzai_total_pgs($content) {
		try {
			$totalpgs = explode('.html" target="_self"',$content);
			$totalpgs = $totalpgs[0];
			$totalpgs = explode('-',$totalpgs);
			$totalpgs = ADD_addslashes($totalpgs[count($totalpgs) - 1],true);
			if ($totalpgs == '') {
				throw new Exception('总页面数提取失败，请确认源页面是否已经发生改变');
			}
		} catch (Exception $e) {
			throw $e;
		}
		return $totalpgs;
	}
	/**
	 * 获取单页中所有漫画的ID
	 * @param string $content	页面内容
	 * @throws Exception
	 */
	private function get_lianzai_manga_ids_by_pg($content) {
		try {
			$totalpgs = explode('</span></form></div> ',$content);
			$totalpgs = $totalpgs[1];
			$totalpgs = explode('<div class="pages">',$totalpgs);
			$totalpgs = $totalpgs[0];
			if ($totalpgs == '') {
				throw new Exception('ID列表提取失败，请确认源页面是否已经发生改变');
			}
		} catch (Exception $e) {
			throw $e;
		}
		
		//抽取ID
		$match_str = "/<dt><a href=\"\/manga-id-(.*).html\"/isU";
		preg_match_all($match_str,$totalpgs,$urln);
		return $urln[1];
	} 
	
	
	
	
//-----------------------系统功能函数部分-------------------------------------
	/**
	 * 页面转码函数
	 * @param string $orgstr	页面内容
	 */
	private function gb2u8($orgstr){
		return mb_convert_encoding($orgstr,"UTF-8","GB2312");
	}
	/**
	 * 
	 * 插入漫画标签信息
	 * @param int $id	漫画ID
	 * @param int $lu	漫画更新时间
	 * @param string $name	漫画名称
	 */
	private function create_name($id,$dt,$name) {
		global $DB;
		//检查是否存在
		$where = 'AND id= ' . $id .'';
		$result = $DB->build_and_exec_query(
			array('select' => 'COUNT(*) as max','from'   => 'flyluotags','where'	=> "1 " . $where ,)
		);	
		//当已经存在的时候更新日期
		if ($result['max'] > 0) {
			return;
		}
		//当不存在时插入
		else{
			$this->do_taginsert($id,$dt,$name,0);
		};
	}
	/**
	 * 插入漫画标签信息(数据库操作部分)
	 * 
	 * @param int $id	漫画ID
	 * @param int $lu	漫画更新时间
	 * @param string $name	漫画名称
	 * @param int $count	漫画总数
	 */
	private function do_taginsert($id,$lu,$name,$count){
			global $DB;
			$DB->do_insert( 'flyluotags', array( 'id'			=> $id,
									   'lastupdate'				=> $lu,
									   'name'					=> $name,
									   'count'					=> $count,
									 )		);
			if ($result === false) {
				show_normal_mesR('无法添加当前漫画','添加出错','添加');
			}
	}
	/**
	 * 获取当前ID的漫画在数据库中的集数
	 * @param int $id	漫画ID
	 */
	private function get_id_count_db($id) {
		global $DB;
		$where = 'AND id= ' . $id .'';
		$result = $DB->build_and_exec_query(
			array('select' => 'count','from'   => 'flyluotags','where'	=> "1 " . $where ,)
		);	
		return $result['count'];;
	}
	/**
	 * 删除由于中断引起的已经插入的内容
	 * @param int $tid	漫画ID
	 * @param string $tbl	漫画表名
	 */
	private function clear_err_picins($tid,$tbl='flyluophotos'){
		global $DB;
		$where = 'uid= ' . $tid .'';
		//检查是否存在
		$result = $DB->build_and_exec_query(
			array('select' => 'COUNT(*) as max','from'   => $tbl,'where'	=> $where ,)
		);	
		//当已经存在的时候删除内容
		if ($result['max'] <= 0) {
			return;
		}
		$DB->simple_delete($tbl,$where);
		$DB->exec_query();
	}
	/**
	 * 重置由于中断引起的原有总量，需配合清空漫画内容函数使用
	 * Enter description here ...
	 * @param unknown_type $tid
	 * @param unknown_type $tbl
	 */
	private function clear_err_tagnums($tid,$tbl='flyluotags'){
		$this->update_manga_info($tid, 0, 0,$tbl);
	}
	/**
	 * 插入图片
	 * @param id $tid	漫画ID
	 * @param string $picurls	当前话的URL图片链接
	 */
	private function do_picinsert($tid,$picurls,$tbl='flyluophotos'){
		$picurls = serialize($picurls);
		global $DB;
		$DB->do_insert( $tbl, array( 'uid'			=> $tid,
								   	 'url'			=> $picurls,
								 )		);
		if ($result === false) {
			show_normal_mesR('无法添加当前漫画','添加出错','添加');
		}
	}
	/**
	 * 更新漫画信息
	 * @param int $tid			漫画ID
	 * @param int $lastupdate	最后更新时间
	 * @param int $count		总量
	 * @param string $tbl		漫画表名
	 */
	private function update_manga_info($tid,$lastupdate,$count,$tbl='flyluotags'){
		global $DB;
		$where = 'id= ' . $tid .'';
		//检查是否存在
		$result = $DB->build_and_exec_query(
			array('select' => 'COUNT(*) as max','from'   => $tbl,'where'	=> $where ,)
		);	
		//当已经存在的时候删除内容
		if ($result['max'] <= 0) {
			return;
		}
		$DB->do_update($tbl,
			array(					  
			   'lastupdate'				=> $lastupdate,
			   'count'					=> $count,
			 ),
			 $where
		);
	}
	/**
	 * 构造最常访问漫画列表
	 *
	 */
	private function get_most_often_seem() {
		global $DB;
		$ccount = $this->ccount;
		$array_ccount = array();
		
		$DB->build_query(array(
				'select' 	=> '*',
				'from'		=> 'flyluotags',
				'order'		=> 'scount DESC',
				'limit'		=> array(0,$this->ccount)
		));
		$qid = $DB->exec_query();
		$i = 0;
		while ($row = $DB->fetch_row($qid)) {
			$array_ccount[$i]['tidname'] = $row['name'];
			$array_ccount[$i]['ccount'] = $row['scount'];
			$array_ccount[$i]['tidlink'] = $this->make_tidlink($row['name']);
			$i++;
		};
		return $array_ccount;
	}
	/**
	 * 初始化模板库并返回库文件
	 * @param string array() $array_piclist	漫画列表数组
	 * @param string array() $sysinfo		系统设置数组
	 * @param string $pagelink				分页字符串
	 * @param string $array_ccount			最常访问漫画字符串
	 */
	private function smarty_show($array_piclist,$sysinfo,$pagelink,$array_ccount) {
		$page = init_smart_template_obj('flyluo/list.html',CACHE_DIR,CACHE_DIR,TEMPLATE_DIR);
		$page->assign("piclist",$array_piclist);
		$page->assign("system",$sysinfo);
		$page->assign("pagelink",$pagelink);
		$page->assign("searchpg",SITE_URL . 'flyluo/search.php');
		$page->assign("title","列表");
		$page->assign("tidlink",$array_ccount);
		$page->assign("ccount",$this->ccount);
		return $page;
	} 
	/**
	 * 通过漫画ID获取其全图片列表
	 * @param unknown_type $tid
	 */
	private function make_manga_pic_links($tid) {
		global $DB;
		
		$DB->build_query(array(
				'select' 	=> '*',
				'from'		=> 'flyluophotos',
				'where'		=>	'uid=' . $tid,
		));
		$qid = $DB->exec_query();
		$pics = '';
		while ($row = $DB->fetch_row($qid)) {
			$pre_urls = unserialize($row['url']);
			foreach ($pre_urls as $v) {
				$pics .= $v . "\r\n";
			}
		};
		return $pics;
	}
	/**
	 * 更新访问计数
	 * @param int $tid	漫画ID
	 */
	private function update_count($tid) {
		global $DB;
		$result = $DB->build_and_exec_query(
				array(
					'select' 	=> 'scount',
					'from'		=> 'flyluotags',
					'where'		=>	'id=' . $tid,
				)
		);
		
		$where = 'id= ' . $tid .'';
		$DB->do_update('flyluotags',
			array(					  
			   'scount'				=> $result['scount'] + 1,
			 ),
			 $where
		);
		
		
	}
	
	
	
	
//------------------------URL构造函数部分-------------------------------------	
	
	/**
	 * 
	 * 获取某漫画的页面列表ID
	 * @param int $id	用于设置需要采集的漫画的ID
	 */
	private function make_manga_url($id){
		return FLYLUO_URL_MANGA_HTTP_HEADER . $id . FLYLUO_URL_MANGA_HTTP_FINISHER;
	}
	/**
	 * 获取连载列表URL
	 * @param int $pid	设置需要访问的页码
	 */
	private function make_lianzai_page_url($pid){
		return FLYLUO_URL_LIANZAI_HTTP_HEADER . $pid . FLYLUO_URL_LIANZAI_HTTP_FINISHER;
	}
	/**
	 * 获取最近更新列表URL
	 * @param int $pid	设置需要访问的页码
	 */
	private function make_update_page_url($pid){
		return FLYLUO_URL_UPDATE_HTTP_HEADER . $pid . FLYLUO_URL_UPDATE_HTTP_FINISHER;
	}
	/**
	 * 构造文件下载列表URL
	 * @param int $id	设置漫画ID
	 */
	private function make_downloadpicslink($id) {
		return SITE_URL . 'flyluo/pics.php?action=getpicfiles&tid=' . $id;
	}
	/**
	 * 构造文字下载列表URL
	 * @param int $id	设置漫画ID
	 */
	private function make_picslink($id) {
		return SITE_URL . 'flyluo/pics.php?action=getpicurls&tid=' .$id;
	}
	/**
	 * 构造采集URL
	 * @param int $id	设置漫画ID
	 */
	private function make_getnewlink($id) {
		return SITE_URL . 'flyluo/cr.php?tid=' .$id;
	}
	/**
	 * 构造分页代码
	 * 如果查询关键字为空，则视为显示INDEX页面
	 * @param string $kw	查询关键字
	 * @param int $st		当前页码
	 */
	private function make_pagelinks() {
		global $Elsesky;
		if ($this->kw == '') {
			$totalnumbers = get_count_of_field('flyluotags','');
			$pagelink = $Elsesky->PageLinkR($this->st,$totalnumbers,$this->listnum,SITE_URL."flyluo/index.php?&st=<:st:>");
		}else {
			$totalnumbers = get_count_of_field('flyluotags','name like "%' . $this->kw . '%"');
			$pagelink = $Elsesky->PageLinkR($this->st,$totalnumbers,$this->listnum,SITE_URL."flyluo/search.php?name=" . $this->kw . "&st=<:st:>");
		}
		return $pagelink;
	}
	/**
	 * 构造基于漫画名称查询的URL
	 * @param int $name	设置漫画名称
	 */
	private function make_tidlink($name) {
		return SITE_URL . 'flyluo/search.php?name=' . $name;
	}
	
//-----------------------框架构造函数部分-------------------------------------
	private static $Instance = null;
	//构造函数
	protected function __construct() {}
	//系统默认方法用于获取当前对象
	public static function getInstance() {
		if (self::$Instance === null) {
			$thisClass = __CLASS__;
			self::$Instance = new $thisClass;
		}
		return self::$Instance;
	}

	
}

?>